;======================================================
;    crt0_multi_boot_arm.s (crt0.s that is compatible with MultiBoot)
;    AGB Startup Routine
;
;    Copyright (C) 1999-2001 NINTENDO Co.,Ltd.
;======================================================

	INCLUDE	    AgbDefineArm.s
	INCLUDE	    AgbMemoryMapArm.s
    INCLUDE     AgbSyscallDefineArm.s
	INCLUDE	    AgbMacroArm.s
    AREA        Init, CODE, READONLY

	GLOBAL		_start
_start
	INCLUDE	     rom_header_arm.s

	b	multiboot_handshake

; Declare as the following examples from C program:
; extern u8 boot_method, boot_channel;
;
; boot_method: 0=ROM boot
;              (1=Reserve)
;              (2=Reserve)
;              3=Multi-play boot
;
; boot_channel: 0=Master (a value that is not possible in serial boot)
;               1-3: Slave No. 1- 3.

	GLOBAL	boot_method
	GLOBAL	boot_channel
boot_method	    DCB		0	; boot method = ROM if it stays as the initial value 0
boot_channel	DCB		0

	DCB		0	; reserved
	DCB		0	; reserved

; The parameter area from host
; Declare as the following examples from C program.
; extern u32 bootparam[6];
;
; Each parameter that is determined at the time of execution can be sent to slaves by setting here.
; If there are no parameters that change by the time of execution will be sent to slaves as in its initial value.

        GLOBAL  bootparam
bootparam
        DCD   0	; bootparam[0]
        DCD   0	; bootparam[1]

        DCD   0
        DCD   0
        DCD   0
        DCD   0

; Handshake subroutine
; Monitors if data being sent by master.
; return: if CPSR flag is bne, error.
	CODE32
multiboot_handshake_poll
	ldrh	r1, [r0, #8]	; REG_SIOCNT
	tst	r1, #SIO_START
	beq	multiboot_handshake_poll
1
	ldrh	r1, [r0, #8]	; REG_SIOCNT
	tst	r1, #SIO_START
	bne	%b1

	ldrh	r1, [r0, #8]	; REG_SIOCNT
	tst	r1, #SIO_ERROR
	bxne	lr	; If error flag is on, error

	ldrh	r1, [r0]
	bx	lr

; Handshake
; (Procedure for telling master that start up okay as multiplay boot slave)
; If start up as multi-play boot, SIO is
; in multi-play boot 115200bps mode.
; At this point, IME=0 so no interrupt.
	CODE32
multiboot_handshake
	ldr	r0, =REG_SIOMLT_RECV

; Monitor if data sent from master
; At first, due to timing of slave startup may have communication error flag
; so monitor if communication error flag not on and start of send from master.
1
	bl	multiboot_handshake_poll
	bne	%b1	; Error

; As an indictaion that slave started up, first return 0x0000.
	mov	r2, #0
	strh	r2, [r0, #0x0a] ; REG_SIODATA8

	cmp	r1, #0
	bne	%b1	; First data must be 0x0000.

	mov	r2, #0x8000	; r2: Data that should come from master/Data slave returns
2
	mov	r1, #0
; Slave also returns data from master.
3
	strh	r1, [r0, #0x0a]	; REG_SIODATA8
	bl	multiboot_handshake_poll
	bne	%b1	; Error

	cmp	r1, r2
	bne	%b2	; Error

; Data required from master came so slave returns same thing.
; Master data comes in order of 0x8000, 0x0400, 0x0020, 0x0001, 0x0000.
; Slave returns 0x8000, 0x0400, 0x0020, 0x0001.
; r1 is 0x8000, 0x0400, 0x0020, 0x0001, 0x0000.
	mov	r2, r2, lsr #5
	cmp	r1, #0
	bne	%b3

; After this if communication error or data doesn't match, slave stops(infinite loop)
; At this point, 0x0000 has come from master.
; Slave returns intial code, low.
	ldr	r3, =0x020000ac
	ldrh	r2, [r3]
	strh	r2, [r0, #0x0a]	; REG_SIODATA8
	bl	multiboot_handshake_poll
5
	bne	%b5	; Error(Infinite Loop)

	cmp	r1, r2
	bne	%b5	; Error(Infinite Loop)

; From master, same initial code low has come.
; Slave returns initial code, high.
	ldrh	r2, [r3, #2]
	strh	r2, [r0, #0x0a]	; REG_SIODATA8
	bl	multiboot_handshake_poll
	bne	%b5	; Error(Infinite Loop)

	cmp	r1, r2
	bne	%b5	; Error(Infinite Loop)

; Handshake end.
; Initialize slave output data register to 0.
; (Handshake process completed so master doesn't receive this data)
	mov	r1, #0
	strh	r1, [r0, #0x0a]	; REG_SIODATA8

;--------------------------------------------------------------------
;-                          Expand Program                          -
;--------------------------------------------------------------------
    EXTERN     _binary_demo_LZ_bin_start
    GLOBAL     start_vector
    CODE32
start_vector
        ldr     r0, =_binary_demo_LZ_bin_start
        ldr     r1, =EX_WRAM + 0x10000
        swi     SWI_NO_LZ77_UNCOMP_WRAM << 16   ; bl  LZ77UnCompWram

        ldr     lr, =EX_WRAM + 0x10000
        bx      lr


	.END


